use std::fs::File;
use std::io::{self, Read, Write};
use std::error::Error;
use std::fmt;

// 自定义错误类型
#[derive(Debug)]
enum CustomError {
    IoError(io::Error),
    InvalidValue(String),
}

impl fmt::Display for CustomError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            CustomError::IoError(err) => write!(f, "IO错误: {}", err),
            CustomError::InvalidValue(msg) => write!(f, "无效的值: {}", msg),
        }
    }
}

impl Error for CustomError {}

impl From<io::Error> for CustomError {
    fn from(err: io::Error) -> CustomError {
        CustomError::IoError(err)
    }
}

// 一个可能失败的函数
fn divide(a: i32, b: i32) -> Result<i32, String> {
    if b == 0 {
        Err(String::from("除数不能为零"))
    } else {
        Ok(a / b)
    }
}

// 使用自定义错误类型的函数
fn read_and_write_file() -> Result<(), CustomError> {
    // 尝试打开文件
    let mut file = File::create("example.txt")?;
    
    // 写入一些内容
    file.write_all(b"Hello, Rust!")?;
    
    // 重新打开文件来读取内容
    let mut file = File::open("example.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    
    if contents.is_empty() {
        return Err(CustomError::InvalidValue("文件内容为空".to_string()));
    }
    
    println!("文件内容: {}", contents);
    Ok(())
}

fn main() {
    println!("=== Rust Result类型示例 ===\n");

    // 1. 基本的Result使用
    println!("1. 基本的Result使用:");
    match divide(10, 2) {
        Ok(result) => println!("10 / 2 = {}", result),
        Err(e) => println!("错误: {}", e),
    }

    match divide(10, 0) {
        Ok(result) => println!("10 / 0 = {}", result),
        Err(e) => println!("错误: {}", e),
    }

    // 2. Result组合器
    println!("\n2. Result组合器使用:");
    let result = divide(10, 2)
        .map(|x| x * 2)  // 如果成功，将结果乘2
        .and_then(|x| Ok(x + 1))  // 链式操作
        .unwrap_or(-1);  // 如果失败，返回-1
    println!("组合器结果: {}", result);

    // 3. 错误传播
    println!("\n3. 错误传播示例:");
    match read_and_write_file() {
        Ok(_) => println!("文件操作成功！"),
        Err(e) => println!("文件操作失败: {}", e),
    }

    // 4. unwrap和expect的使用
    println!("\n4. unwrap和expect的使用:");
    println!("unwrap成功示例: {}", divide(10, 2).unwrap());
    println!("expect成功示例: {}", divide(8, 4).expect("除法运算失败"));
    
    // 下面这行会导致panic
    // println!("这行会panic: {}", divide(10, 0).unwrap());

    println!("\n所有示例执行完成！");
}